﻿/* **************************************************************************
 *
 * Copyright 2007-2010 Jeff Hardy
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * *************************************************************************/

using System.Collections;
using System.Configuration;
using System.Web.Configuration;
using System.Collections.Generic;

namespace NWSGI
{
    public class WsgiSection : ConfigurationSection, NWSGI.IWsgiConfig
    {
        public static WsgiSection Load()
        {
            return ConfigurationManager.GetSection("wsgi") as WsgiSection ?? new WsgiSection();
        }

        public bool DebugMode
        {
            get { return ((CompilationSection)ConfigurationManager.GetSection("system.web/compilation")).Debug; }
        }

        [ConfigurationProperty("enableExtensions", DefaultValue = false)]
        public bool EnableExtensions
        {
            get { return this["enableExtensions"] as bool? ?? false; }
            set { this["enableExtensions"] = value; }
        }

        [ConfigurationProperty("compilation", DefaultValue = CompilationOptions.Adaptive)]
        public CompilationOptions Compilation
        {
            get { return this["compilation"] as CompilationOptions? ?? CompilationOptions.Adaptive; }
            set { this["compilation"] = value; }
        }

        [ConfigurationProperty("frames", DefaultValue = FrameOptions.Off)]
        public FrameOptions Frames
        {
            get { return this["frames"] as FrameOptions? ?? FrameOptions.Off; }
            set { this["frames"] = value; }
        }

        [ConfigurationProperty("tracing", DefaultValue = false)]
        public bool Tracing
        {
            get { return this["tracing"] as bool? ?? false; }
            set { this["tracing"] = value; }
        }

        [ConfigurationProperty("lightweightScopes", DefaultValue = false)]
        public bool LightweightScopes
        {
            get { return this["lightweightScopes"] as bool? ?? false; }
            set { this["lightweightScopes"] = value; }
        }

        [ConfigurationProperty("enableProfiler", DefaultValue = false)]
        public bool EnableProfiler
        {
            get { return this["enableProfiler"] as bool? ?? false; }
            set { this["enableProfiler"] = value; }
        }

        public bool HasWildcard
        {
            get { return this.Wildcard.ElementInformation.IsPresent; }
        }

        [ConfigurationProperty("wildcard")]
        public WildcardElement Wildcard
        {
            get { return this["wildcard"] as WildcardElement; }
            set { this["wildcard"] = value; }
        }

        IWildcardInfo IWsgiConfig.Wildcard
        {
            get { return this.Wildcard; }
        }

        [ConfigurationProperty("pythonPaths")]
        [ConfigurationCollection(typeof(PythonPathCollection))]
        public PythonPathCollection PythonPaths
        {
            get { return this["pythonPaths"] as PythonPathCollection; }
        }

        IEnumerable<string> IWsgiConfig.PythonPaths
        {
            get 
            { 
                foreach(PythonPathElement path in this.PythonPaths)
                {
                    yield return path.Path;
                }
            }
        }

        [ConfigurationProperty("wsgiEnviron")]
        [ConfigurationCollection(typeof(WsgiEnvironCollection))]
        public WsgiEnvironCollection WsgiEnviron
        {
            get { return this["wsgiEnviron"] as WsgiEnvironCollection; }
        }

        IEnumerable<KeyValuePair<string, string>> IWsgiConfig.WsgiEnviron
        {
            get 
            {
                foreach(WsgiEnvironElement envvar in this.WsgiEnviron)
                {
                    yield return new KeyValuePair<string, string>(envvar.Name, envvar.Value);
                }
            }
        }

        [ConfigurationProperty("scriptMappings")]
        [ConfigurationCollection(typeof(ScriptMappingCollection))]
        public ScriptMappingCollection ScriptMappings
        {
            get { return this["scriptMappings"] as ScriptMappingCollection; }
        }

        IEnumerable<IScriptMappingInfo> IWsgiConfig.ScriptMappings
        {
            get 
            { 
                foreach(IScriptMappingInfo scriptMapping in this.ScriptMappings) 
                { 
                    yield return scriptMapping; 
                }
            }
        }
    }

    #region Wildcard Settings

    public class WildcardElement : ConfigurationElement, IWildcardInfo
    {
        [ConfigurationProperty("physicalPath", IsRequired = false)]
        public string PhysicalPath
        {
            get { return (string)this["physicalPath"]; }
            set { this["physicalPath"] = value; }
        }

        [ConfigurationProperty("callable", IsRequired = false, DefaultValue = "application")]
        public string Callable
        {
            get { return (string)this["callable"]; }
            set { this["callable"] = value; }
        }
    }

    #endregion

    #region Paths

    public class PythonPathCollection : ConfigurationElementCollection
    {
        public override ConfigurationElementCollectionType CollectionType
        {
            get { return ConfigurationElementCollectionType.BasicMap; }
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new PythonPathElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((PythonPathElement)element).Path;
        }

        protected override string ElementName
        {
            get { return "path"; }
        }
    }

    public class PythonPathElement : ConfigurationElement
    {
        public PythonPathElement() { }

        public PythonPathElement(string path)
        {
            this.Path = path;
        }

        [ConfigurationProperty("path", IsRequired = true, DefaultValue = "No description.")]
        public string Path
        {
            get { return (string)this["path"]; }
            set { this["path"] = value; }
        }
    }

    #endregion

    #region WSGI Environ

    public class WsgiEnvironCollection : ConfigurationElementCollection
    {
        public override ConfigurationElementCollectionType CollectionType
        {
            get { return ConfigurationElementCollectionType.BasicMap; }
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new WsgiEnvironElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((WsgiEnvironElement)element).Name;
        }

        protected override string ElementName
        {
            get { return "variable"; }
        }
    }

    public class WsgiEnvironElement : ConfigurationElement
    {
        public WsgiEnvironElement() { }

        public WsgiEnvironElement(string name, string value)
        {
            this.Name = name;
            this.Value = value;
        }

        [ConfigurationProperty("name", IsRequired = true, DefaultValue = "WSGI environment variable name.")]
        public string Name
        {
            get { return (string)this["name"]; }
            set { this["name"] = value; }
        }

        [ConfigurationProperty("value", IsRequired = true, DefaultValue = "WSGI environment variable value.")]
        public string Value
        {
            get { return (string)this["value"]; }
            set { this["value"] = value; }
        }
    }

    #endregion

    #region Script Mappings

    public class ScriptMappingCollection : ConfigurationElementCollection
    {
        public override ConfigurationElementCollectionType CollectionType
        {
            get { return ConfigurationElementCollectionType.BasicMap; }
        }

        protected override ConfigurationElement CreateNewElement()
        {
            return new ScriptMappingElement();
        }

        protected override object GetElementKey(ConfigurationElement element)
        {
            return ((ScriptMappingElement)element).ScriptName;
        }

        protected override string ElementName
        {
            get { return "scriptMapping"; }
        }
    }

    public class ScriptMappingElement : ConfigurationElement, IScriptMappingInfo
    {
        [ConfigurationProperty("scriptName", IsKey = true, IsRequired = true)]
        public string ScriptName
        {
            get { return (string)this["scriptName"]; }
            set { this["scriptName"] = value; }
        }

        [ConfigurationProperty("physicalPath", IsRequired = false)]
        public string PhysicalPath
        {
            get { return (string)this["physicalPath"]; }
            set { this["physicalPath"] = value; }
        }

        [ConfigurationProperty("callable", IsRequired = false, DefaultValue = "application")]
        public string Callable
        {
            get { return (string)this["callable"]; }
            set { this["callable"] = value; }
        }
    }

    #endregion
}
